package com.itheima.health.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.itheima.health.entity.TMember;
import com.itheima.health.entity.TOrder;
import com.itheima.health.mapper.TMemberMapper;
import com.itheima.health.pojo.vo.*;
import com.itheima.health.service.ITMemberService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.health.service.ITOrderService;
import com.itheima.health.service.ITSetmealCheckgroupService;
import com.itheima.health.service.ITSetmealService;
import org.apache.poi.ss.formula.functions.Count;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author cpanda
 * @since 2024-01-30
 */
@Service
public class TMemberServiceImpl extends ServiceImpl<TMemberMapper, TMember> implements ITMemberService {

    @Autowired
    ITOrderService orderService;
    @Autowired
    ITSetmealCheckgroupService setmealCheckgroupService;
    @Autowired
    ITSetmealService setmealService;

    /**
     * 运营数量统计
     *
     * @return
     */
    @Override
    public BusinessReportVO BusinessReportData() {
        BusinessReportVO vo = new BusinessReportVO();
        LocalDate today = LocalDate.now();//当前日期
        //月
        LocalDate startOfMonth = today.with(TemporalAdjusters.firstDayOfMonth());
        LocalDate endOfMonth = today.with(TemporalAdjusters.lastDayOfMonth());
        //周
        //根据当前日期获得本周开始日期
        LocalDate startOfWeek = today.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
        //根据当前日期获得本周结束日期
        LocalDate endOfWeek = today.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
        /**
         * 会员
         */
        //新增会员数  今日
        int count = dayCount(today);
        //总会员数量
        int totalCount = this.count();
        //本周
        int weekCount = weekCount(startOfWeek, endOfWeek);
        //本月
        int monthCount = weekCount(startOfMonth, endOfMonth);
        //今日预约数量
        Integer dayOrderCount = dayOrderCount(today, null);
        //预约到诊数据
        Integer dayOrderCountStuatus = dayOrderCount(today, "已到诊");
        //本周预约数量
        Integer weekOrderCount=weekOrderCount(startOfWeek,endOfWeek,null);
        //本周到诊数量
        Integer weekOrderCountStuatus=weekOrderCount(startOfWeek,endOfWeek,"已到诊");
        //本月预约数量
        Integer mouthOrderCount=mouthOrderCount(startOfMonth,endOfMonth,null);
        //本月到诊数量
        Integer mouthOrderCountStuatus=mouthOrderCount(startOfMonth,endOfMonth,"已到诊");
        //掉用套餐接口
        SetmealReportVO setmealReport = setmealCheckgroupService.getSetmealReport();
        //套餐预约总数量
        int totalCountSetmeal = setmealService.count();
        List<ReportVO> setmealCount = setmealReport.getSetmealCount();
        List<HotSetmealVO> voList=new ArrayList<>();
        for (ReportVO reportVO : setmealCount) {
            HotSetmealVO hotSetmealVO = new HotSetmealVO();

            String name = reportVO.getName();
            Integer value = reportVO.getValue();
            //占比
            BigDecimal proportion = BigDecimal.valueOf(value).divide(BigDecimal.valueOf(totalCountSetmeal), 4,BigDecimal.ROUND_HALF_UP);

            hotSetmealVO.setName(name);
            hotSetmealVO.setSetmealCount(value);
            hotSetmealVO.setProportion(proportion);
            voList.add(hotSetmealVO);
        }
        vo.setReportDate(today);
        vo.setTodayNewMember(count);
        vo.setTotalMember(totalCount);
        vo.setThisWeekNewMember(weekCount);
        vo.setThisMonthNewMember(monthCount);
        vo.setTodayOrderNumber(dayOrderCount);
        vo.setTodayVisitsNumber(dayOrderCountStuatus);
        vo.setThisWeekOrderNumber(weekOrderCount);
        vo.setThisWeekVisitsNumber(weekOrderCountStuatus);
        vo.setThisMonthOrderNumber(mouthOrderCount);
        vo.setThisMonthVisitsNumber(mouthOrderCountStuatus);
        vo.setHotSetmeal(voList);
        return vo;
    }
    /**
     * 本月预约数量,本月到诊数量
     */
    public int mouthOrderCount(LocalDate start, LocalDate end, String status) {
        LambdaQueryWrapper<TOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.gt(TOrder::getOrderDate, start)
                .lt(TOrder::getOrderDate, end)
                .eq(status != null, TOrder::getOrderStatus, status);
        int count = orderService.count(queryWrapper);
        return count;
    }

    /**
     * 本周预约数量,本周到诊数量
     */
    public int weekOrderCount(LocalDate start, LocalDate end, String status) {
        LambdaQueryWrapper<TOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.gt(TOrder::getOrderDate, start)
                    .lt(TOrder::getOrderDate, end)
                    .eq(status != null, TOrder::getOrderStatus, status);
        int count = orderService.count(queryWrapper);
        return count;
    }

    /**
     * 今日预约数量,今日到诊数量
     */
    public int dayOrderCount(LocalDate today, String status) {
        LambdaQueryWrapper<TOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TOrder::getOrderDate, today)
                    .eq(status != null, TOrder::getOrderStatus, status);
        int count = orderService.count(queryWrapper);
        return count;
    }

    /**
     * 当月新增会员数量
     */
    public int monthCount(LocalDate start, LocalDate end) {
        Integer monthCount = lambdaQuery().gt(TMember::getRegTime, start)
                .lt(TMember::getRegTime, end)
                .count();
        return monthCount;
    }

    /**
     * 当天日期新增会员数量
     */
    private int dayCount(LocalDate today) {
        LambdaQueryWrapper<TMember> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TMember::getRegTime, today);
        int count = this.count(queryWrapper);
        return count;
    }

    /**
     * 获取本周新增会员数量
     */
    private Integer weekCount(LocalDate start, LocalDate end) {
        Integer weekCount = lambdaQuery().gt(TMember::getRegTime, start)
                .lt(TMember::getRegTime, end)
                .count();
        return weekCount;
    }


    /**
     * 统计会员数量
     */
    @Override
    public ReportMemberVO getMemberReport() {
        List<TMember> memberList = this.list();
        //取出来所有的时间
        List<LocalDate> dateList = memberList.stream().map(r -> r.getRegTime()).collect(Collectors.toList());
        ReportMemberVO memberVO = new ReportMemberVO();
        //根据时间 yyyy-MM-dd 转为yyyy-MM  然后进行分组
        Map<String, Long> monthCount = dateList.stream()
                .map(date -> date.format(DateTimeFormatter.ofPattern("yyyy-MM"))) // 将日期格式化为 "yyyy-MM" 格式
                .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));// 重新收集为Map // 按月份分组并计数
        List<String> listDate = new ArrayList<>();
        List<Long> numberList = new ArrayList<>();
        monthCount.forEach((m, n) -> {
            listDate.add(m);
            numberList.add(n);
        });
        memberVO.setMemberCount(numberList);
        memberVO.setMonths(listDate);
        return memberVO;
    }
}
